﻿using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
using smp.QueryDb.Structure;

namespace smp.QueryDb
{
    public class NestedMap<TViewModel>
    {
        private readonly List<Map> _maps = new List<Map>();
        
        internal List<Map> Maps {get { return _maps; } }

        public INestedMapTo<TViewModel> Map(Expression<Func<TViewModel, object>> propertyExpression)
        {
            var property = Helper.GetExpressionProperty(propertyExpression.Body);
            if (property == null)
            {
                throw Helper.Error("Invalid property expression {0}", propertyExpression.Body);
            }
            return new NestedMapTo<TViewModel>(this, property);
        }

        public INestedMapTo<TViewModel> Map(string propertyName)
        {
            var property = Helper.GetNamedProperty<TViewModel>(propertyName);
            if (property == null)
            {
                throw Helper.Error("Invalid property name {0} for type {1}",
                                   propertyName,
                                   typeof (TViewModel).Name);
            }
            return new NestedMapTo<TViewModel>(this, property);
        }

        public INestedMapAllTo<TViewModel> MapAllProperties()
        {
            return new NestedMapAllTo<TViewModel>(this);
        }

        internal void AddMap(PropertyInfo property, Column column)
        {
            if (_maps.Find(x => x.Property.Name == property.Name) != null)
            {
                throw Helper.Error("Duplicate property mapping declaration, cannot map property {0} twice.", property.Name);
            }
            var map = new Map(property, column);
            _maps.Add(map);
        }

        internal void AddNestedMap(PropertyInfo property, List<Map> maps)
        {
            if (_maps.Find(x => x.Property.Name == property.Name) != null)
            {
                throw Helper.Error("Duplicate property mapping declaration, cannot map property {0} twice.", property.Name);
            }
            var nestedMap = new Map(property, maps);
            _maps.Add(nestedMap);
        }
    }
}
